/**
 * Created by ${PRODUCT_NAME}.
 * User: skylerparr
 * Date: 12/29/10
 * Time: 10:48 PM
 * To change this template use File | Settings | File Templates.
 */
package com.thoughtorigin.module {
import com.thoughtorigin.loader.mock.MockLoaderInfo;
import com.thoughtorigin.service.Service;
import com.thoughtorigin.service.ServiceLocator;

import flash.display.Loader;
import flash.system.ApplicationDomain;
import flash.utils.Dictionary;
import flash.utils.getQualifiedClassName;

import org.flexunit.asserts.assertEquals;
import org.flexunit.asserts.assertNotNull;
import org.flexunit.asserts.assertNull;
import org.mockito.integrations.any;
import org.mockito.integrations.between;
import org.mockito.integrations.given;
import org.mockito.integrations.mock;
import org.mockito.integrations.verify;

[RunWith("org.mockito.integrations.flexunit4.MockitoClassRunner")]
[Mock(type="com.thoughtorigin.service.ServiceLocator")]
[Mock(type="com.thoughtorigin.service.Service")]
[Mock(type="com.thoughtorigin.module.Module")]
[Mock(type="flash.display.Loader")]
public class DefaultModuleLoaderTest {

    private var _moduleLoader: TestableDefaultModuleLoader;
    private var _serviceLocator: ServiceLocator;

    [Before]
    public function setup(): void {
        _moduleLoader = new TestableDefaultModuleLoader();
        _serviceLocator = mock(ServiceLocator);
    }

    [After]
    public function tearDown(): void {
        _moduleLoader = null;
        _serviceLocator = null;
    }

    [Test]
    public function shouldLoadModuleStoreServicesInTheServiceLocator(): void {
        var service: Service = mock(Service);
        var module: Module = mock(Module);
        var name: String = getQualifiedClassName(module);

        given(_serviceLocator.addService);
        var dict: Dictionary = new Dictionary(true);
        dict["serviceName"] = service;
        given(module.services).willReturn(dict);
        given(module.applicationDomain).willReturn(ApplicationDomain.currentDomain);

        _moduleLoader.serviceLocator = _serviceLocator;
        _moduleLoader.loadModule(module);

        verify(between(1,1)).that(_serviceLocator.addService(any()));
        verify(between(1,2)).that(module.services);
        assertNotNull(_moduleLoader.getRegisteredModules()[name]);
        assertEquals(module, _moduleLoader.getRegisteredModules()[name]);
        assertNotNull(_moduleLoader.registeredApplicationDomains[name])
    }

    [Test]
    public function shouldUnloadModuleAndUnloadTheServices(): void {
        var service: Service = mock(Service);
        var module: Module = mock(Module);
        var name: String = getQualifiedClassName(module);

        var dict: Dictionary = new Dictionary(true);
        dict["serviceName"] = service;
        given(module.services).willReturn(dict);
        given(module.applicationDomain).willReturn(ApplicationDomain.currentDomain);
        var mockLI: TestableAbstractLoaderInfo = new TestableAbstractLoaderInfo(null);
        var mockLoader: Loader = mock(Loader);
        mockLI.loader = mockLoader;
        given(module.abstractLoaderInfo).willReturn(mockLI);
        given(mockLoader.unloadAndStop);

        _moduleLoader.serviceLocator = _serviceLocator;
        _moduleLoader.unloadModule(module);

        verify(between(1,1)).that(_serviceLocator.removeService(any()));
        verify(between(1,1)).that(module.unloadModule());
        verify(between(1,2)).that(module.services);
        verify(between(1,1)).that(module.abstractLoaderInfo);
        verify(between(1,1)).that(mockLI.loader);
        verify(between(1,1)).that(mockLoader.unloadAndStop);
        assertNull(_moduleLoader.getRegisteredModules()[name]);
        assertNull(_moduleLoader.registeredApplicationDomains[name]);
    }
}
}

import com.thoughtorigin.loader.AbstractLoaderInfo;
import com.thoughtorigin.module.DefaultModuleLoader;

import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.utils.Dictionary;

class TestableDefaultModuleLoader extends DefaultModuleLoader {

    public function getRegisteredModules(): Dictionary {
        return registeredModules;
    }
}

class TestableAbstractLoaderInfo extends AbstractLoaderInfo {

    private var _loader: Loader;

    public function TestableAbstractLoaderInfo(loaderInfo:LoaderInfo) {
        super(loaderInfo);
    }

    override public function get loader():Loader {
        return _loader;
    }

    public function set loader(value:Loader):void {
        _loader = value;
    }
}
